package cn.com.hhrcw.web;

import static cn.com.hhrcw.utils.DateUtil.getLastMonths;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.aspect.annotation.PermissionData;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.vo.DictModel;
import org.jeecg.common.system.vo.LoginUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import cn.com.hhrcw.entity.CvUserEduInfo;
import cn.com.hhrcw.entity.CvUserWorkInfo;
import cn.com.hhrcw.entity.CvWorkIntention;
import cn.com.hhrcw.entity.EnInfo;
import cn.com.hhrcw.entity.OpDeliveryHistory;
import cn.com.hhrcw.entity.OpJob;
import cn.com.hhrcw.entity.PiInfo;
import cn.com.hhrcw.entity.SsSession;
import cn.com.hhrcw.mapstruct.AdminCvUserEduInfoConvert;
import cn.com.hhrcw.mapstruct.AdminCvUserWorkInfoConvert;
import cn.com.hhrcw.mapstruct.AdminCvWorkIntentionConvert;
import cn.com.hhrcw.mapstruct.AdminOpJobConvert;
import cn.com.hhrcw.mapstruct.AdminPiInfoConvert;
import cn.com.hhrcw.mapstruct.EnInfoAdminConvert;
import cn.com.hhrcw.mapstruct.SsSessionAdminConvert;
import cn.com.hhrcw.params.OpJobParams;
import cn.com.hhrcw.service.ICvUserEduInfoService;
import cn.com.hhrcw.service.ICvUserWorkInfoService;
import cn.com.hhrcw.service.ICvWorkIntentionService;
import cn.com.hhrcw.service.IEnInfoService;
import cn.com.hhrcw.service.IOpDeliveryHistoryService;
import cn.com.hhrcw.service.IOpJobService;
import cn.com.hhrcw.service.IPiInfoService;
import cn.com.hhrcw.service.ISsSessionService;
import cn.com.hhrcw.vo.OpJobVO;
import cn.com.hhrcw.vo.SsUserInfoVO;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

/**
 * 职位-职位本位
 *
 * @author jiangdong
 * @since 2020-10-29
 */
@RestController
@Slf4j
@RequestMapping("/admin/opJob")
@Api(tags = "职位-职位本位")
@Validated
public class AdminOpJobController extends JeecgController<OpJob, IOpJobService> {

    @Autowired
    private IOpJobService opJobService;

    @Autowired
    private AdminOpJobConvert enOpJobConvert;

    @Autowired
    private IOpDeliveryHistoryService deliveryHistoryService;

    @Autowired
    private IPiInfoService piInfoService;

    @Autowired
    private ICvUserEduInfoService eduInfoService;

    @Autowired
    private AdminCvUserEduInfoConvert eduInfoConvert;

    @Autowired
    private AdminPiInfoConvert enPiInfoConvert;

    @Autowired
    EnInfoAdminConvert enInfoAdminConvert;

    @Autowired
    private ICvUserWorkInfoService workInfoService;

    @Autowired
    private AdminCvUserWorkInfoConvert workInfoConvert;

    @Autowired
    private ICvWorkIntentionService workIntentionService;

    @Autowired
    private AdminCvWorkIntentionConvert workIntentionConvert;

    @Autowired
    private IEnInfoService enInfoService;

    @Autowired
    private ISsSessionService ssSessionService;

    @Autowired
    private SsSessionAdminConvert ssSessionAdminConvert;

    /**
     * 职位管理-职位列表
     *
     * @param params 专场id必传
     * @return
     */
    @GetMapping("/getJobList")
    @AutoLog(logType = 2, ty = "visit", value = "职位管理列表")
    public Result<Page<OpJobVO>> getJobListBySessionId(OpJobParams params) {
        LambdaQueryWrapper<OpJob> jobQuery = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(params.getJobName())) {
            jobQuery.like(OpJob::getJobName, params.getJobName());
        }
        //置顶
        if (params.getRecommendFlag() != null) {
            jobQuery.eq(OpJob::getRecruitmentFlag, params.getRecommendFlag());
        }

        if (params.getRecruitmentState() != null) {
            jobQuery.eq(OpJob::getRecruitmentState, params.getRecruitmentState());
        }

        if (StringUtils.isNotBlank(params.getJobName())) {
            jobQuery.like(OpJob::getJobName, params.getJobName());
        }
        if (params.getRecruitType() != null) {
            jobQuery.eq(OpJob::getRecruitType, params.getRecruitType());
        }

        //公司名称模糊查询
        if (StringUtils.isNotBlank(params.getCompanyName())) {
            List<EnInfo> enInfos = enInfoService.lambdaQuery().like(EnInfo::getEnName, params.getCompanyName()).list();
            if (CollUtil.isNotEmpty(enInfos)) {
                jobQuery.in(OpJob::getCompanyId, enInfos.stream().map(EnInfo::getId).toArray());
            } else {
                return Result.ok(new Page<>());
            }
        }
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        if(StringUtils.isNotBlank(sysUser.getAdminDivision())){
            //省级用户
            List<EnInfo> enInfos = new ArrayList<>();
            if(sysUser.getAdminDivision().endsWith("0000")){
                enInfos = enInfoService.lambdaQuery().eq(EnInfo::getProvince, sysUser.getAdminDivision()).list();
            }else {
                //市级用户
                if ("410100".equals(sysUser.getAdminDivision())) {
                    //郑州
                    enInfos = enInfoService.lambdaQuery().eq(EnInfo::getCity, sysUser.getAdminDivision())
                            .ne(EnInfo::getEnAddress, "410000,410100,410173").list();
                } else  if ("410173".equals(sysUser.getAdminDivision())) {
                    //判断是否为航空港区
                    enInfos = enInfoService.lambdaQuery().eq(EnInfo::getEnAddress, "410000,410100,410173").list();
                }else {
                    //不是郑州
                    enInfos = enInfoService.lambdaQuery().eq(EnInfo::getCity, sysUser.getAdminDivision()).list();
                }
            }
            if (CollUtil.isNotEmpty(enInfos)) {
                jobQuery.in(OpJob::getCompanyId, enInfos.stream().map(EnInfo::getId).toArray());
            }else{
                jobQuery.eq(OpJob::getCompanyId, "null");
            }
            List<DictModel> models = sysBaseApi.queryDictItemsByCode("gxt_ss_session");
            if(CollUtil.isNotEmpty(models)){
                jobQuery.in(OpJob::getBsId, models.stream().map(DictModel::getValue).toArray());
            }else{
                jobQuery.eq(OpJob::getId,"null");
            }
        }
        if (StringUtils.isNotBlank(params.getSsSessionId())) {
            jobQuery.eq(OpJob::getBsId, params.getSsSessionId());
        }
        if (StringUtils.isNotBlank(params.getBsId())) {
            jobQuery.eq(OpJob::getBsId, params.getBsId()).eq(OpJob::getBsType, params.getBsType());
        }
        //发布时间查询
        if (params.getUpdateTime_begin() != null && params.getUpdateTime_end()!=null) {
//            jobQuery.between(OpJob::getUpdateTime, params.begin(OpJobParams::getUpdateTime), params.end(OpJobParams::getUpdateTime));
            jobQuery.between(OpJob::getCreateTime, params.getUpdateTime_begin(), params.getUpdateTime_end());
        }
        jobQuery.eq(OpJob::getDelFlag, false).orderByDesc(OpJob::getCreateTime);
        IPage<OpJob> page = opJobService.page(params.page(), jobQuery);
        Function<OpJob, OpJobVO> fun = job -> {
            OpJobVO vo = enOpJobConvert.toVO(job);
            // 0 未阅读  1 已阅读 2 不合适 3通过筛选4 面试 5已发offer(已录用) 6 已入职 7 被系统过滤 8未入职9反馈面试结果(通过)10反馈面试结果(不通过)
            //已入职
            LambdaQueryWrapper<OpDeliveryHistory> historyQuery = new LambdaQueryWrapper<>();
            historyQuery.eq(OpDeliveryHistory::getDelFlag, false).eq(OpDeliveryHistory::getJobId, vo.getId()).eq(OpDeliveryHistory::getState, 6);
            int countAlready = deliveryHistoryService.count(historyQuery);
            vo.setAlreadyCount(countAlready);

            //未阅简历
            LambdaQueryWrapper<OpDeliveryHistory> notRead = new LambdaQueryWrapper<>();
            notRead.eq(OpDeliveryHistory::getDelFlag, false).eq(OpDeliveryHistory::getJobId, vo.getId()).eq(OpDeliveryHistory::getState, 0);
            int notReadCount = deliveryHistoryService.count(notRead);
            vo.setNotReadCount(notReadCount);
            //目标人选
            LambdaQueryWrapper<OpDeliveryHistory> stepQuery = new LambdaQueryWrapper<>();
            stepQuery.eq(OpDeliveryHistory::getDelFlag, false).eq(OpDeliveryHistory::getJobId, vo.getId()).eq(OpDeliveryHistory::getState, 3);
            int stepCount = deliveryHistoryService.count(stepQuery);
            vo.setStepCount(stepCount);

            if (job.getBsType() != null && job.getBsType() == 1) {
                SsSession ssSession = ssSessionService.getById(job.getBsId());
                vo.setSession(ssSessionAdminConvert.toVO(ssSession));
            }

            EnInfo enInfo = enInfoService.getById(job.getCompanyId());
            vo.setEnInfo(enInfoAdminConvert.toVO(enInfo));

            //待招人数=招聘人数-已入职人数
            return vo;
        };
        return Result.ok((Page) page.convert(fun));
    }

    /**
     * 职位置顶
     *
     * @param params
     * @return
     */
    @PostMapping("/top")
    @AutoLog(logType = 2, ty = "update", value = "职位指定")
    public Result top(@RequestBody OpJobParams params) {
        OpJob job = this.opJobService.getById(params.getId());
        job.setRecommendFlag(true);
        job.setRecommendNo(params.getRecommendNo());
        boolean updated = this.opJobService.updateById(job);
        return updated ? Result.ok() : Result.error("置顶失败");
    }

    /**
     * 职位管理-某个职位的投递情况
     *
     * @param params
     * @param request
     * @return
     */
    @GetMapping("/getUserList")
    @AutoLog(logType = 2, ty = "visit", value = "查询职位投递记录")
    public Result<Page<SsUserInfoVO>> getUserList(OpJobParams params, HttpServletRequest request) {
        LambdaQueryWrapper<OpJob> jobLambdaQueryWrapper = new LambdaQueryWrapper<>();
        jobLambdaQueryWrapper.eq(OpJob::getDelFlag, false).eq(OpJob::getId, params.getId());
        if (StringUtils.isNotBlank(params.getJobName())) {
            jobLambdaQueryWrapper.like(OpJob::getJobName, params.getJobName());
        }
        if (StringUtils.isNotBlank(params.getCompanyId())) {
            jobLambdaQueryWrapper.eq(OpJob::getCompanyId, params.getCompanyId());
        }
        if (StringUtils.isNotBlank(params.getId())) {
            jobLambdaQueryWrapper.eq(OpJob::getId, params.getId());
        }
        List<OpJob> jobs = service.list(jobLambdaQueryWrapper);
        if (!CollectionUtils.isEmpty(jobs)) {
            List<String> jobIds = new ArrayList<>();
            jobs.forEach(e -> {
                jobIds.add(e.getId());
            });
            LambdaQueryWrapper<OpDeliveryHistory> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(OpDeliveryHistory::getDelFlag, false).in(OpDeliveryHistory::getJobId, jobIds);
            if (StringUtils.isNotBlank(params.getUserId())) {
                queryWrapper.eq(OpDeliveryHistory::getUserId, params.getUserId());
            }
            if (StringUtils.isNotBlank(params.getUserName())) {
                LambdaQueryWrapper<PiInfo> infoQuery = new LambdaQueryWrapper<>();
                infoQuery.like(PiInfo::getName, params.getUserName()).eq(PiInfo::getDelFlag, false);
                List<PiInfo> piInfoList = piInfoService.list(infoQuery);
                if (CollectionUtils.isEmpty(piInfoList)) {
                    return Result.ok(new Page<>());
                } else {
                    List<String> userIds = new ArrayList<>();
                    piInfoList.forEach(e -> {
                        userIds.add(e.getUserId());
                    });
                    queryWrapper.in(OpDeliveryHistory::getUserId, userIds);
                }
            }

            if (params.getEduLevel() != null) {
                //0 初中  1 高中 2 中专/中技 3 大专 4 本科 5 硕士 6 MBA/EMBA  7 博士
                LambdaQueryWrapper<CvUserEduInfo> eduQuery = new LambdaQueryWrapper<>();
                eduQuery.eq(CvUserEduInfo::getDelFlag, false).eq(CvUserEduInfo::getEduLevel, params.getEduLevel());
                List<CvUserEduInfo> eduInfos = eduInfoService.list(eduQuery);
                if (CollectionUtils.isEmpty(eduInfos)) {
                    return Result.ok(new Page<>());
                } else {
                    List<String> userIds = new ArrayList<>();
                    eduInfos.forEach(e -> {
                        userIds.add(e.getUserId());
                    });
                    queryWrapper.in(OpDeliveryHistory::getUserId, userIds);
                }
            }
            if (params.getTimeState() != null) {

                if (0 == params.getTimeState()) {
                    queryWrapper.ge(OpDeliveryHistory::getCreateTime, getLastMonths(3));
                } else if (1 == params.getTimeState()) {
                    queryWrapper.ge(OpDeliveryHistory::getCreateTime, getLastMonths(6));
                }

            }
            IPage<OpDeliveryHistory> page = deliveryHistoryService.page(params.page(), queryWrapper);
            Function<OpDeliveryHistory, SsUserInfoVO> function = opDeliveryHistory -> {
                SsUserInfoVO vo = new SsUserInfoVO();
                vo.setDataId(opDeliveryHistory.getId());

                LambdaQueryWrapper<CvUserEduInfo> eduQuery = new LambdaQueryWrapper<>();
                eduQuery.eq(CvUserEduInfo::getDelFlag, false).eq(CvUserEduInfo::getUserId, opDeliveryHistory.getUserId());
                List<CvUserEduInfo> eduInfos = eduInfoService.list(eduQuery);
                vo.setEduInfo(eduInfoConvert.toVO(eduInfos));

                OpJob job = service.getById(opDeliveryHistory.getJobId());
                vo.setJobName(job.getJobName());
                vo.setJobTime(opDeliveryHistory.getCreateTime());

                LambdaQueryWrapper<PiInfo> infoLambdaQueryWrapper = new LambdaQueryWrapper<>();
                infoLambdaQueryWrapper.eq(PiInfo::getDelFlag, false).eq(PiInfo::getUserId, opDeliveryHistory.getUserId());
                PiInfo piInfo = piInfoService.getOne(infoLambdaQueryWrapper);
                vo.setUserInfo(enPiInfoConvert.toVO(piInfo));

                LambdaQueryWrapper<CvUserWorkInfo> workInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
                workInfoLambdaQueryWrapper.eq(CvUserWorkInfo::getDelFlag, false).eq(CvUserWorkInfo::getUserId, opDeliveryHistory.getUserId());
                List<CvUserWorkInfo> workInfos = workInfoService.list(workInfoLambdaQueryWrapper);
                vo.setWorkInfo(workInfoConvert.toVO(workInfos));

                LambdaQueryWrapper<CvWorkIntention> workIntentionLambdaQueryWrapper = new LambdaQueryWrapper<>();
                workIntentionLambdaQueryWrapper.eq(CvWorkIntention::getDelFlag, false).eq(CvWorkIntention::getUserId, opDeliveryHistory.getUserId());
                List<CvWorkIntention> workIntentions = workIntentionService.list(workIntentionLambdaQueryWrapper);
                vo.setWorkIntention(workIntentionConvert.toVO(workIntentions));
                return vo;
            };
            return Result.ok((Page) page.convert(function));
        }
        return Result.ok(new Page<>());
    }

    /**
     * 职位管理-发布职位
     *
     * @param params 请求参数
     * @return
     */
    @PostMapping(value = "/add")
    @AutoLog(logType = 2, ty = "insert", value = "职位添加")
    @ApiOperation(value = "添加", notes = "添加")
    public Result<?> add(@RequestBody @Valid OpJobParams params) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        OpJob opJob = enOpJobConvert.toEntity(params);
        opJob.setCreateBy(sysUser.getId());
        opJob.setCreateTime(DateUtil.date());
        opJob.setDelFlag(false);
        opJob.setRecruitmentState(0);
        boolean saved = opJobService.save(opJob);
        return saved ? Result.ok() : Result.error("添加失败");
    }

    /**
     * 职位管理-职位修改
     *
     * @param params 请求参数
     * @return
     */
    @PostMapping(value = "/editJob")
    @AutoLog(logType = 2, ty = "update", value = "职位编辑")
    @ApiOperation(value = "编辑", notes = "编辑")
    public Result<?> edit(@RequestBody @Valid OpJobParams params) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        OpJob opJob = enOpJobConvert.toEntity(params);
        opJob.setUpdateBy(sysUser.getId());
        opJob.setUpdateTime(DateUtil.date());
        boolean updated = opJobService.updateById(opJob);
        return updated ? Result.ok() : Result.error("编辑失败");
    }

    /**
     * 职位管理-职位复制
     *
     * @param id 职位id
     * @return
     */
    @GetMapping(value = "/copy")
    @AutoLog(logType = 2, ty = "update", value = "职位复制")
    @ApiOperation(value = "复制", notes = "复制")
    public Result<?> copy(@NotBlank(message = "职位id必填") String id) {
        OpJob job = opJobService.getById(id);
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        job.setId(null);
        String jobName = job.getJobName() + " COPY";
        job.setJobName(jobName);
        job.setRecruitmentState(1);
        job.setCreateBy(sysUser.getId());
        job.setCreateTime(DateUtil.date());
        job.setUpdateBy(sysUser.getId());
        job.setUpdateTime(DateUtil.date());
        job.setCloseTime(DateUtil.date());
        if (job.getSysFrom() == 1) {
            job.setSysFrom(2);
        }
        boolean updated = opJobService.save(job);
        return updated ? Result.ok() : Result.error("复制失败");
    }

    /**
     * 职位管理-删除职位
     *
     * @param id 数据id
     * @return
     */
    @GetMapping(value = "/deleteJob")
    @AutoLog(logType = 2, ty = "delete", value = "职位删除")
    @ApiOperation(value = "批量删除", notes = "批量删除")
    public Result delete(String[] id) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        List<OpJob> list = opJobService.lambdaQuery().in(OpJob::getId, id).list();
        list.stream().map(e -> e.setDelFlag(true)).forEach(opJobService::updateById);
        return Result.ok();
    }

    /**
     * 根据id查询职位详情
     *
     * @param id 数据id
     * @return
     */
    @GetMapping(value = "/queryById")
    @ApiOperation(value = "根据id查询", notes = "根据id查询")
    @AutoLog(logType = 2, ty = "visit", value = "查询职位信息")
    @PermissionData
    public Result<OpJobVO> queryById(String id) {
        OpJob opJob = opJobService.lambdaQuery().eq(OpJob::getId, id).eq(OpJob::getDelFlag, false).one();
        if (opJob == null) {
            throw new JeecgBootException("数据不存在");
        }
        return Result.ok(enOpJobConvert.toVO(opJob));
    }

    /**
     * 发布或关闭职位
     *
     * @param id
     * @return
     */
    @GetMapping("/publishOrClose")
    @AutoLog(value = "发布或关闭职位", logType = 2, ty = "update")
    public Result<?> publishOrClose(@NotBlank(message = "职位id必填") String id) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        OpJob job = this.opJobService.getById(id);
        if (job.getRecruitmentState().intValue() == 0) {
            job.setRecruitmentState(1);
            job.setCloseTime(DateUtil.date());
        } else {
            //是否专场
            if(StringUtils.isNotBlank(job.getBsId()) && 1 == job.getBsType()){
                SsSession ssSession = ssSessionService.lambdaQuery().eq(SsSession::getId, job.getBsId()).eq(SsSession::getDelFlag, false).one();
                if (ssSession != null || ssSession.getPostShelfManage()) {
                    return Result.error("该职位发布受专场负责人整体管控,不允许单独发布");
                }
            }
            job.setRecruitmentState(0);
        }
        return  this.opJobService.updateById(job) ? Result.ok() : Result.error("修改失败");
    }

}
